package com.kk.utils;

import com.fazecast.jSerialComm.SerialPort;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

public class PortUtils {

    private static final ConcurrentHashMap<String, Future<?>> taskMap = new ConcurrentHashMap<>();

    private static final ThreadPoolTaskExecutor poolExecutor = new ThreadPoolTaskExecutor();

    public static void main(String[] args) throws InterruptedException {
        String ATB_CMD = "CP";
        String ATB_EXP = "CPOK";

        String BTP_CMD = "CP";
        String BTP_EXP = "CPOK";

        poolExecutor.setCorePoolSize(10);
        poolExecutor.setMaxPoolSize(100);
        poolExecutor.setKeepAliveSeconds(30);
        poolExecutor.setAwaitTerminationSeconds(600);
        poolExecutor.setQueueCapacity(200);
        poolExecutor.setThreadNamePrefix("use-port-");
        poolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        poolExecutor.setWaitForTasksToCompleteOnShutdown(false);
        poolExecutor.initialize();

        // open all
        SerialPort[] serialPorts = SerialPort.getCommPorts();

//        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
//            poolExecutor.shutdown();
//            System.err.println("close all ports.");
//            Arrays.stream(serialPorts).forEach(SerialPort::closePort);
//        }));

        for (SerialPort serialPort : serialPorts) {
            Future<?> future = poolExecutor.submit(() -> {
                try {
                    // 配置串口参数
                    serialPort.setBaudRate(9600);      // 波特率
                    serialPort.setNumDataBits(8);      // 数据位
                    serialPort.setNumStopBits(1);      // 停止位
                    serialPort.setParity(SerialPort.NO_PARITY); // 校验位
                    serialPort.setComPortTimeouts(
                            SerialPort.TIMEOUT_READ_BLOCKING,
                            10000,
                            0
                    );//设置读写超时时间

                    String systemPortName = serialPort.getSystemPortName();

                    // 串口是否占用
                    boolean open = serialPort.isOpen();
                    System.out.println(systemPortName + " is using, " + open);

                    boolean b = serialPort.openPort();
                    System.out.println(systemPortName + " open result: " + b);

                    // 6. 发送数据
                    String message = "\u0002CP\u0003";
                    byte[] sendData = message.getBytes();
                    long start = System.currentTimeMillis();
                    serialPort.writeBytes(sendData, sendData.length);
                    System.out.println(systemPortName + " 发送数据: " + message);

                    // 等待响应
                    byte[] buffer = new byte[1024];
                    while ((System.currentTimeMillis() - start) < serialPort.getReadTimeout()
                            && !Thread.currentThread().isInterrupted()) {
                        int numRead = serialPort.readBytes(buffer, buffer.length);
                        if (numRead > 0) {
                            String response = new String(buffer, 0, numRead);
                            System.out.println(serialPort.getSystemPortName() + " ==收到响应: " + response);

                            // 满足条件时关闭当前线程
                            if (response.contains("OK")) {
                                System.out.println(serialPort.getSystemPortName() + " 任务完成，关闭连接");
                                break;
                            }
                        }
                        Thread.sleep(100);
                    }
                    System.out.println(serialPort.getSystemPortName() + " 任务完成");

                    // 8. 关闭串口
//                    serialPort.closePort();
//                    System.out.println("串口已关闭");
                } catch (Throwable e) {
                    System.err.println(e.getMessage());
                } finally {
                    serialPort.closePort();
                    taskMap.remove(serialPort.getSystemPortName());
                }
            });

            taskMap.put(serialPort.getSystemPortName(), future);
        }
//        taskMap.forEach((k,v)->v.cancel(true));


        while (true) {
            if (poolExecutor.getActiveCount() == 1) {
                taskMap.forEach((k,v)->v.cancel(true));
//                System.exit(0);
                poolExecutor.setAwaitTerminationSeconds(5);
                poolExecutor.shutdown();
                break;
            }
            System.out.println("poolExecutor.getActiveCount() = " + poolExecutor.getActiveCount());
            Thread.sleep(1000);
        }
//        System.out.println("over");
//
    }
}
